package com.tiantian.user.controller;

import cn.dev33.satoken.secure.BCrypt;
import cn.hutool.core.bean.BeanUtil;
import com.tiantian.common.core.constant.CacheConstants;
import com.tiantian.common.core.domain.ResponseResult;
import com.tiantian.common.core.utils.StringUtils;
import com.tiantian.common.idempotent.annotation.RepeatSubmit;
import com.tiantian.common.log.annotation.Log;
import com.tiantian.common.log.enums.BusinessType;
import com.tiantian.common.ratelimiter.annotation.RateLimiter;
import com.tiantian.common.ratelimiter.enums.LimitType;
import com.tiantian.common.redis.utils.RedisUtils;
import com.tiantian.common.satoken.domain.controller.BaseController;
import com.tiantian.common.satoken.utils.LoginHelper;
import com.tiantian.user.domain.dto.UserPasswordDto;
import com.tiantian.user.domain.dto.UserProfileDto;
import com.tiantian.user.domain.entity.SysUser;
import com.tiantian.user.service.SysUserService;
import jakarta.validation.constraints.Email;
import jakarta.validation.constraints.NotBlank;
import lombok.RequiredArgsConstructor;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import java.util.concurrent.TimeUnit;


/**
 * 个人信息 业务处理
 */
@Validated
@RequiredArgsConstructor
@RestController
@RequestMapping("/user/profile")
public class SysProfileController extends BaseController {

    private final SysUserService userService;

    /**
     * 获取用户个人信息
     */
    @GetMapping
    public ResponseResult<SysUser> profile() {
        SysUser user = userService.selectUserById(getUserId());
        return ResponseResult.ok(user);
    }

    /**
     * 修改用户信息
     */
    @PutMapping
    @Log(businessType = BusinessType.UPDATE_PROFILE)
    @RepeatSubmit(interval = 5, timeUnit = TimeUnit.SECONDS)
    public ResponseResult<Void> updateProfile(@RequestBody @Validated UserProfileDto userProfileDTO) {
        SysUser user = BeanUtil.copyProperties(userProfileDTO, SysUser.class);
        Long userId = getUserId();

        SysUser sysUser = userService.selectUserById(userId);
        if (!sysUser.getPhonenumber().equals(userProfileDTO.getPhonenumber()) && !userService.checkPhoneUnique(user)) {
            return ResponseResult.fail("修改手机号码[" + user.getPhonenumber() + "]失败，该手机号码已存在");
        }
        // 修改昵称-判断是否为成员是则同步修改判题人信息

        user.setUserId(userId);
        if (userService.updateUserProfile(user) > 0) {
            deleteUserInfoCache(userId);
            return ResponseResult.ok();
        }
        return ResponseResult.fail("修改个人信息异常,请联系管理员");
    }

    @PutMapping("/updateEmail")
    @Log(businessType = BusinessType.UPDATE_PROFILE)
    public ResponseResult<Void> updateEmail(@NotBlank(message = "邮箱不能为空") String email,
                                            @Email(message = "新邮箱格式不正确") String newEmail,
                                            @NotBlank(message = "验证码不能为空") String captcha) {
        String key = CacheConstants.UPDATE_EMAIL_CAPTCHA_CODE_KEY + email;
        String captchaForRedis = RedisUtils.getCacheObject(key);

        if (StringUtils.isEmpty(captchaForRedis) || !captcha.equals(captchaForRedis)) {
            return ResponseResult.fail("验证码不正确");
        }
        SysUser user = new SysUser();
        user.setUserId(getUserId());
        user.setEmail(newEmail);
        if (!userService.checkEmailUnique(user)) {
            return ResponseResult.fail("修改用户[" + user.getEmail() + "]失败，邮箱账号已存在");
        }
        if (userService.updateUserProfile(user) > 0) {
            deleteUserInfoCache(user.getUserId());
            return ResponseResult.ok();
        }
        return ResponseResult.fail("修改邮箱,请联系管理员");
    }

    /**
     * 重置密码
     */
    @PostMapping("/updatePwd")
    @Log(businessType = BusinessType.UPDATE_PWD, isSaveRequestData = false)
    @RateLimiter(time = 120, count = 1, limitType = LimitType.IP)
    public ResponseResult<Void> updatePwd(@RequestBody @Validated UserPasswordDto userPasswordDTO) {
        String newPassword = userPasswordDTO.getNewPassword();
        String oldPassword = userPasswordDTO.getOldPassword();
        String confirmPassword = userPasswordDTO.getConfirmPassword();

        if (!newPassword.equals(confirmPassword)) {
            return ResponseResult.fail("两次密码输入不一致");
        }
        SysUser user = userService.selectUserById(LoginHelper.getUserId());
        String password = user.getPassword();
        if (!BCrypt.checkpw(oldPassword, password)) {
            return ResponseResult.fail("修改密码失败,旧密码错误");
        }
        if (BCrypt.checkpw(newPassword, password)) {
            return ResponseResult.fail("新密码不能与旧密码相同");
        }
        Long userId = getUserId();
        if (userService.resetUserPwd(userId, BCrypt.hashpw(newPassword)) > 0) {
            deleteUserInfoCache(userId);
            return ResponseResult.ok();
        }
        return ResponseResult.fail("修改密码异常,请联系管理员");
    }

    private void deleteUserInfoCache(Long userId) {
        RedisUtils.deleteObject(CacheConstants.USER_INFO_KEY + userId);
    }


}
